/**
 * 
 */
package annotool.clustering;

import java.util.ArrayList;
import java.util.Vector;

import mpicbg.imagefeatures.Feature;

/**
 * @author DIVAKARUNI
 *
 */
public class CodeBook 
{

	/**
	 * 
	 */
	public int featureSize;
	float[][] features;
	int length = 0;
	int dimension = 0;
	int maxClass;
	float[][] testingFeatures,  selectedTrainingFeatures;
	float[][][] testingfeaturesperimage, codebook;

	// closest/next closest neighbour distance ratio
	//private float rod = 0.92f;

	public CodeBook(float[][] testingFeatures, float[][] selectedTrainingFeatures, int featureSize) 
	{
		this.featureSize = featureSize;
		this.testingFeatures = testingFeatures;
		this.selectedTrainingFeatures = selectedTrainingFeatures;
	}

	public float[][] generator() 
	{
		features = new float[testingFeatures.length][];
		testingfeaturesperimage = getFeaturesPerImage(testingFeatures);
		codebook = getFeaturesPerImage(selectedTrainingFeatures);
		
		for(int i = 0; i < testingfeaturesperimage.length; i++)
		{
			Vector<Feature> fs2 = new Vector<Feature>();
			for(int perfeat = 0; perfeat < testingfeaturesperimage[i].length; perfeat++)
				fs2.add(new Feature(testingfeaturesperimage[i][perfeat]));
			ArrayList<Float> ratio = new ArrayList<Float>(); 

			for(int j = 0; j < codebook.length; j++)
			{
				Float[][] featurefloats2d = new Float[testingfeaturesperimage.length][featureSize];
				Vector<Feature> fs1 = new Vector<Feature>();
				for(int perfeat = 0; perfeat < codebook[j].length; perfeat++)
					fs1.add(new Feature(codebook[j][perfeat]));
				for ( Feature original : fs1)
				{
					float d = 0;
					Feature f1 = original;
					Feature best = null;
					float best_d = Float.MAX_VALUE;
					float second_best_d = Float.MAX_VALUE;
						
						for ( Feature f2 : fs2 )
						{
							d = f1.descriptorDistance( f2 );
							if ( d < best_d )
							{
								second_best_d = best_d;
								best_d = d;
								best = f2;
							}
							else if ( d < second_best_d )
								second_best_d = d;
						}
						float abc = best_d/second_best_d;
						if ( best != null && second_best_d < Float.MAX_VALUE )
							{
							float r_d = abc;
							
							float rd = best_d;
							r_d = r_d * rd;
							//r_d = rd;
							Feature fc = f1;
							featurefloats2d[i] = fc.toFloats();
							float sr_d = 1 - r_d;
							//System.out.println("the vals "+r_d+" and "+rd);
							//System.out.println("the ges"+featurefloats2d[i][0]+" "+featurefloats2d[i][1]+" "+featurefloats2d[i][2]+" "+featurefloats2d[i][3]+" ");
							//System.out.println("the size after"+matches.size());			
							ratio.add(sr_d);
							}
				}
				
		}
			features[i] = new float[ratio.size()];
			//System.out.println("rep: "+ratio.size());
			for(int r = 0; r < ratio.size(); r++)
			{
				features[i][r] = ratio.get(r);
				//System.out.print(" "+(r+1)+":"+features[i][r]);

			}
			//System.out.println();
		}
		return features;
	}
	
	float[][][] getFeaturesPerImage(float[][] getfeatures)
	{
		float[][][] featuresperimage;

		featuresperimage = new float[getfeatures.length][][];

		for(int i = 0;i < getfeatures.length; i++)
		{
			featuresperimage[i] = new float[(getfeatures[i].length)/featureSize][featureSize];

			for(int j = 0;j < (getfeatures[i].length)/featureSize; j++)
			{
			 	for(int k = 0;k < featureSize;k++)
				{
					featuresperimage[i][j][k] = getfeatures[i][(j * featureSize) + k];
				}

			}

		 }
		return featuresperimage;
	}

}
